package cn.xmall.services.cn.xmall.services.impl;

import cn.xmall.caches.UserCache;
import cn.xmall.commons.utils.HttpRequestUtils;
import cn.xmall.mappers.UserMapper;
import cn.xmall.models.User;
import cn.xmall.services.UserService;
import cn.xmall.services.cn.xmall.services.WeiXinUserService;
import cn.xmall.vo.WxUserInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

@Service
public class WeiXinUserServiceImpl implements WeiXinUserService {

    @Value("${wxsp_AppID}")
    private String wxspAppID;

    @Value("${wxsp_Secret}")
    private String wxspSecret;

    @Value("${wxsp_Jscode2sessionUrl}")
    private String wxspJscode2SessionUrl;

    final private String grant_type = "authorization_code";

    final String wxUserPrefix="wx_";

    @Autowired
    UserService userService;

    @Autowired
    UserMapper userMapper;

    @Autowired
    UserCache userCache;


     private WxLoginReturn jscode2session(String code) throws Exception {
        Assert.hasText(code,"code is empty");
        //1. 向微信服务器 使用登录凭证 code 获取 session_key 和 openid
        String params = "appid=" + wxspAppID + "&secret=" + wxspSecret
                + "&js_code=" + code + "&grant_type=" + grant_type;
        String sr=HttpRequestUtils.sendGet(wxspJscode2SessionUrl,params);
        WxLoginReturn wxReturn= JSON.parseObject(sr,WxLoginReturn.class);

        return wxReturn;
    }
    /**
     *
     * @param code 微信用户的code
     * @return 自身用户服务生成的token
     */
    @Override
    @Transactional
    public String login(String code) throws Exception {
        WxLoginReturn wxLoginReturn=jscode2session(code);

        Assert.notNull(wxLoginReturn,"wxLoginReture is null");
        Assert.hasText(wxLoginReturn.openid,"openId is empty");
        Assert.hasText(wxLoginReturn.session_key,"sessionId is empty");

        String wxUserName=wxUserPrefix+wxLoginReturn.openid;
        User user=userService.getByUserName(wxUserName);

        //如果用户没有注册，注册用户
        if(user==null){
            user=registerWxUser(wxLoginReturn.openid,wxLoginReturn.session_key);
        }

        String token=loginWxUser(user,wxLoginReturn.openid,wxLoginReturn.session_key);
        return token;
    }

    private String loginWxUser(User user,String openId,String session_key) throws Exception {
        Assert.notNull(user,"user is null");
        Assert.hasText(openId,"openId is empty");
        Assert.hasText(session_key,"sessionId is empty");

        user.setPassword(session_key);
        user.setUpdated(null);
        user.setCreated(null);

        String token= UUID.randomUUID().toString();
        userCache.save(token,user);

        return token;
    }

    /**
     *
     * @param code
     * @return
     */
    @Override
    @Transactional
    public void register(String code) throws Exception {
        Assert.hasText(code,"code is empty");
        //Assert.hasText(phone,"phone  is empty");
        WxLoginReturn wxLoginReturn=jscode2session(code);
        registerWxUser(wxLoginReturn.openid,wxLoginReturn.session_key);
    }


    private User registerWxUser(String openId,String session_key) throws Exception{
        Assert.hasText(openId,"openId is empty");
        Assert.hasText(session_key,"session_key is empty");
        User user=new User();
        user.setUsername(wxUserPrefix+openId);
        user.setPassword(session_key);
        user.setCreated(new Date());
        user.setUpdated(new Date());

        userMapper.insert(user);

        return user;
    }

    @Override
    public boolean isRegiteredWxUser(String openId) throws Exception {

        User user=userService.getByUserName(wxUserPrefix+openId);
        if(user==null){
            return true;
        }

        return false;
    }

    @Override
    public User getLoginedUserByToken(String token){
        User user=userCache.getByTokenKey(token);
        return user;
    }

    static class WxLoginReturn{
        private String openid;
        private String session_key;

        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }

        public String getSession_key() {
            return session_key;
        }

        public void setSession_key(String session_key) {
            this.session_key = session_key;
        }
    }
}
